package com.fingard.dsp.bank.directbank.lianlianpay01;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.lianlianpay01.LianLianPay01Bean.PaymentRequestBean;
import com.fingard.dsp.bank.directbank.lianlianpay01.LianLianPay01Bean.PaymentResponseBean;
import com.fingard.dsp.bank.directbank.lianlianpay01.LianLianPay01Bean.QueryPaymentRequestBean;
import com.fingard.dsp.bank.directbank.lianlianpay01.LianLianPay01Bean.QueryPaymentResponseBean;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.text.StringHelper;

/**
 * 连连平台付款及付款查询接口
 */
public class LianLianPay01SinglePay extends LianLianPay01Base implements ISinglePay {

    /**
     * 单笔付款申请
     * @param p_req1908
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        try{
            PaymentRequestBean paymentRequestBean = new PaymentRequestBean();
            paymentRequestBean.setNo_order(p_req1908.singleDetail.askNumber);//商户订单号
            paymentRequestBean.setDt_order(Format.DateTime14Format.format(p_req1908.singleDetail.getPayDateTime()));//商户订单时间。格式为 YYYYMMddHHmmss
            paymentRequestBean.setMoney_order(p_req1908.singleDetail.payAmount);//交易金额。单位为元，精确到小数点后两位，取值范围为 0.01 ~ 99999999
            paymentRequestBean.setCard_no(p_req1908.singleDetail.recAct);//收款方银行账号
            paymentRequestBean.setAcct_name(p_req1908.singleDetail.recName);//收款方姓名
            paymentRequestBean.setBank_name(p_req1908.singleDetail.cnapsName);//收款银行名称
            paymentRequestBean.setPrcptcd(p_req1908.singleDetail.cnapsCode);//大额行号
            if(!"1".equals(p_req1908.singleDetail.isPrivate)){
                paymentRequestBean.setBank_code(getBankConfig().getMapValueByKey("actAndBankCodeMapping"
                        ,p_req1908.singleDetail.recAct));//银行编码
            }
            paymentRequestBean.setInfo_order(p_req1908.singleDetail.purpose);//订单描述。说明付款用途，5W以上必传
            paymentRequestBean.setFlag_card("1".equals(p_req1908.singleDetail.isPrivate)?"0":"1");//对公对私标志。0 - 对私。1 - 对公。
            paymentRequestBean.setMemo(StringHelper.hasAnyChar(p_req1908.singleDetail.memo)?p_req1908.singleDetail.memo
                    :p_req1908.singleDetail.purpose);//收款备注。 传递至银行， 一般作为订单摘要展示
            paymentRequestBean.setNotify_url("abc");//接收付款结果回调异步通知地址
            paymentRequestBean.setOid_partner(p_req1908.singleDetail.payAct);//商户编号；相当于付款账号
            paymentRequestBean.setApi_version(getBankConfig().getValueAsString("version"));//当前版本
            paymentRequestBean.setSign_type("RSA");//RSA
            paymentRequestBean.setSign(genRSASign(JSON.parseObject(JSON.toJSONString(paymentRequestBean))));//用商户自己的私钥加签
            String jsonStr = JSON.toJSONString(paymentRequestBean);
            WriteBankLogStep2(jsonStr);
            // 用银通公钥对请求参数json字符串加密
            String encryptStr = encryptByBankPublicKey(jsonStr, getBankConfig().getValueAsString("publicKeyOnline"));
            if (StringHelper.isNullOrEmpty(encryptStr)) {
                // 加密异常
                throw new Exception("加密异常");
            }
            JSONObject json = new JSONObject();
            json.put("oid_partner", p_req1908.singleDetail.payAct);
            json.put("pay_load", encryptStr);
            String[] bankResult = sendToBank(json.toJSONString(),p_req1908.reqHeader.transType,p_req1908.reqHeader.commandCode);
            if(bankResult[0].length()==0){
                PaymentResponseBean paymentResponseBean = JSONObject.parseObject(bankResult[1], PaymentResponseBean.class);
                if(paymentRequestBean!=null && StringHelper.hasAnyChar(paymentResponseBean.getRet_code())){
                    if(StringHelper.hasAnyChar(paymentResponseBean.getSign())){
                        // 先对结果验签
                        boolean signCheck = checkSignByPubKey(getBankConfig().getValueAsString("publicKeyOnline"),
                                genSignData(JSONObject.parseObject(bankResult[1])), paymentResponseBean.getSign());
                        if (!signCheck) {
                            //传送数据被篡改，可抛出异常，再人为介入检查原因
                            throw new Exception("返回结果验签异常,可能数据被篡改,请检查");
                        }
                        //0000 已生成连连支付单，付款处理中（交易成功，不是指付款成功，是指跟连连流程正常），商户可以在这里处理自已的业务逻辑（或者不处理，在异步回调里处理逻辑）,最终的付款状态由异步通知回调告知
                        // 当调用付款申请接口返回4002，4003，4004,会同时返回验证码，用于确认付款接口
                        // 对于疑似重复订单，需先人工审核这笔订单是否正常的付款请求，而不是系统产生的重复订单，确认后再调用确认付款接口或者在连连商户站后台操作疑似订单，api不调用确认付款接口
                        // 对于疑似重复订单，也可不做处理
                        // 出现1002，2005，4006，4007，4009，9999这6个返回码时（或者对除了0000之后的code都查询一遍查询接口）调用付款结果查询接口，明确订单状态，不能私自设置订单为失败状态，以免造成这笔订单在连连付款成功了，而商户设置为失败
                        // 第一次测试对接时，返回{"ret_code":"4007","ret_msg":"敏感信息解密异常"},可能原因报文加密用的公钥改动了,demo中的公钥是连连公钥，商户生成的公钥用于上传连连商户站用于连连验签，生成的私钥用于加签
                        // 返回其他code时，可将订单置为失败
                        detail.respCode = "0";
                        detail.respInfo = paymentResponseBean.getRet_code()+"："+paymentResponseBean.getRet_msg();
                        detail.reqSeqID =p_req1908.singleDetail.askNumber;
                        detail.transState = paymentResponseBean.getRet_code();
                        detail.payInfoCode = detail.transState;
                    }else {
                        //返回sign为空，无法验签，异常处理，通过付款状态查询最终状态
                        //1001不返回 1004不返回 1008不返回 3001不返回
                        detail.respCode ="-1";
                        detail.respInfo = paymentResponseBean.getRet_code()+":"+paymentResponseBean.getRet_msg();
                    }
                }else {
                    detail.respCode ="-1";
                    detail.respInfo = "返回信息异常";
                }
            }else {
                // 出现异常时调用订单查询，明确订单状态，不能私自设置订单为失败状态，以免造成这笔订单在连连付款成功了，而商户设置为失败
                detail.respCode ="-1";
                detail.respInfo = bankResult[1];
            }
        }catch (Exception e){
            detail = new RetAtsSglDetail();
            detail.respCode = "-1";
            detail.respInfo = e.getMessage();
        }
        retAts.writeRetDetail(detail);
        return retAts;
    }

    /**
     * 单笔付款结果查询
     * @param p_req1944
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        try{
            QueryPaymentRequestBean queryPaymentRequestBean = new QueryPaymentRequestBean();
            queryPaymentRequestBean.setNo_order(p_req1944.askNumber);//商户付款流水号
            //queryPaymentRequestBean.setOid_paybill("");//连连银通付款流水号
            queryPaymentRequestBean.setOid_partner(p_req1944.payAct);//商户编号
            queryPaymentRequestBean.setApi_version(getBankConfig().getValueAsString("version"));//api当前版本号
            queryPaymentRequestBean.setSign_type("RSA");//签名方式
            queryPaymentRequestBean.setSign(genRSASign(JSON.parseObject(JSON.toJSONString(queryPaymentRequestBean))));//签名方
            String jsonStr = JSON.toJSONString(queryPaymentRequestBean);
            String[] bankResult = sendToBank(jsonStr,p_req1944.reqHeader.transType,p_req1944.reqHeader.commandCode);
            if(bankResult[0].length()==0){
                QueryPaymentResponseBean queryPaymentResponseBean = JSONObject.parseObject(bankResult[1], QueryPaymentResponseBean.class);
                if(queryPaymentResponseBean!=null){
                    if("0000".equals(queryPaymentResponseBean.getRet_code())){
                        // 先对结果验签
                        boolean signCheck = checkSignByPubKey(getBankConfig().getValueAsString("publicKeyOnline"),
                                genSignData(JSONObject.parseObject(bankResult[1])), queryPaymentResponseBean.getSign());
                        if (!signCheck) {
                            //传送数据被篡改，可抛出异常，再人为介入检查原因
                            throw new Exception("返回结果验签异常,可能数据被篡改");
                        }else {
                            tmpRetAtsDetail.respCode = "0";
                            tmpRetAtsDetail.respInfo = queryPaymentResponseBean.getRet_msg();
                            tmpRetAtsDetail.reqSeqID = queryPaymentResponseBean.getNo_order();
                            tmpRetAtsDetail.transState = queryPaymentResponseBean.getResult_pay();
                            tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                        }
                    }else {
                        //ret_code=0000时根据订单状态处理，其他当作异常处理
                        tmpRetAtsDetail.respCode ="-1";
                        if("8901".equals(queryPaymentResponseBean.getRet_code())){
                            //返回ret_code=8901没有记录
                            //查询时间距离付款请求时间半个小时返回ret_code=8901无记录才能置为失败
                            tmpRetAtsDetail.respInfo = queryPaymentResponseBean.getRet_msg()+"，如付款超过半小时，请人工确认状态";
                        }else {
                            tmpRetAtsDetail.respInfo = queryPaymentResponseBean.getRet_msg();
                        }
                    }
                }else {
                    tmpRetAtsDetail.respCode ="-1";
                    tmpRetAtsDetail.respInfo = "响应内容为空";
                }
            }else {
                // 出现异常时调用订单查询，明确订单状态，不能私自设置订单为失败状态，以免造成这笔订单在连连付款成功了，而商户设置为失败
                tmpRetAtsDetail.respCode ="-1";
                tmpRetAtsDetail.respInfo = bankResult[0];
            }
        }catch (Exception e){
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }
}
